using AspectCore.Extensions.DependencyInjection;
using LdtCommonLogger;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Web;
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace NlpApp.Webapi
{
    /// <summary>
    /// Program
    /// </summary>
#pragma warning disable S1118 // Utility classes should not have public constructors
    public class Program
#pragma warning restore S1118 // Utility classes should not have public constructors
    {
        private static bool isRunProcessEnd = false;
#pragma warning disable CS0618 // 类型或成员已过时
        private static NLog.Logger logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
#pragma warning restore CS0618 // 类型或成员已过时
        /// <summary>
        /// Defines the entry point of the application.
        /// </summary>
        /// <param name="args">The arguments.</param>
        public static void Main(string[] args)
        {
            RunProcess("python", "serverLitieExtract.py");
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            try
            {
                while (true)
                {
                    if (isRunProcessEnd)
                    {
                        var db = Path.Combine(AppContext.BaseDirectory, "localdb");
                        if (!File.Exists(db))
                        {
                            File.Copy(Path.Combine(AppContext.BaseDirectory, "localbase"), db);
                        }
                        logger.Info($"已启动...");
                        var versionInfo = FileVersionInfo.GetVersionInfo(Path.Combine(AppContext.BaseDirectory, $"{nameof(NlpApp)}.{nameof(NlpApp.Webapi)}.dll"));
                        LoggerExtend.SetVersion(versionInfo.FileVersion);
                        var t = CreateHostBuilder(args).Build();
                        t.Run();
                        break;
                    }
                    else
                    {
                        logger.Info($"等待启动...");
                        Thread.Sleep(1000);
                    }
                }
            }
            catch (Exception exception)
            {
                //NLog: catch setup errors
                logger.Error(exception, "Stopped program because of exception");
                throw;
            }
            finally
            {
                // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
                NLog.LogManager.Shutdown();
            }
        }
        private static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
        {
            var ex = (e.ExceptionObject as Exception);
            logger.Error(ex, "UnhandledException");
        }
        private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs ex)
        {
            logger.Error(ex.Exception, "UnhandledException");
            ex.SetObserved();
        }
        /// <summary>
        /// Creates the host builder.
        /// </summary>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
              .ConfigureAppConfiguration((hostingContext, config) =>
              {
                  //重新指定配置文件基础目录
                  config.SetBasePath(AppContext.BaseDirectory);
                  //config.AddJsonFile()
              })
              .ConfigureWebHostDefaults(webBuilder =>
              {
                  //重新指定静态文件路径地址
                  webBuilder.UseWebRoot(Path.Combine(System.AppContext.BaseDirectory, "wwwroot"));
                  webBuilder.UseStartup<Startup>().ConfigureKestrel(opt =>
                  {
                      opt.Limits.MinRequestBodyDataRate = null;
                      //opt.Limits.MaxRequestBodySize = int.MaxValue;//限制请求长度
                  }
                  );
              })
              .ConfigureLogging(logging =>
              {
                  logging.ClearProviders();
                  logging.SetMinimumLevel(LogLevel.Debug);
              })
            .UseServiceProviderFactory(new DynamicProxyServiceProviderFactory())
            .UseNLog();
        static Process myProcess = new Process();
        /// <summary>
        /// 运行外部程序
        /// </summary>
        /// <param name="fileName">程序文件</param>
        /// <param name="appParam">程序参数</param>
        /// <returns></returns>
        private static void RunProcess(string fileName, string appParam)
        {
            try
            {
                DirectoryInfo dir = new DirectoryInfo(AppContext.BaseDirectory);
                string servicePath = Path.Combine(dir.Parent.FullName, "python");
                ProcessStartInfo myProcessStartInfo;
                myProcessStartInfo = new ProcessStartInfo(fileName, appParam);
                myProcessStartInfo.WorkingDirectory = servicePath;
                myProcessStartInfo.WindowStyle = ProcessWindowStyle.Normal;
                myProcess.StartInfo = myProcessStartInfo;
                myProcess.StartInfo.RedirectStandardOutput = true;
                myProcess.StartInfo.UseShellExecute = false;          //不显示shell                    
                                                                      //myProcess.StartInfo.CreateNoWindow = true;            //不创建窗口  
                                                                      // myProcess.StartInfo.RedirectStandardInput = true;     //打开流输入  
                myProcess.StartInfo.RedirectStandardError = true;     //打开错误流  
                                                                      // myProcess.StandardInput.AutoFlush = true;             //每次调用 Write()之后，将其缓冲区刷新到基础流
                                                                      //myProcess.ErrorDataReceived += MyProcess_ErrorDataReceived;//
                myProcess.OutputDataReceived += MyProcess_ErrorDataReceived;
                myProcess.Start();
                //myProcess.BeginErrorReadLine();//
                myProcess.BeginOutputReadLine();
            }
            catch (Exception ex)
            {
                Console.Write("出现错误" + ex.Message);
                isRunProcessEnd = true;
            }
        }
        private static void MyProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null)
            {
                Console.WriteLine(e.Data);
                if (!isRunProcessEnd && e.Data.Contains("12008"))
                {
                    isRunProcessEnd = true;
                }
            }
        }
    }
}
